package org.shreker.plugins.test.view;

import com.intellij.openapi.ui.Messages;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
import org.shreker.plugins.test.bean.DataBaseInfo;
import org.shreker.plugins.test.bean.JDBCConnector;

/**
 * @Author: ShrekerNil
 * @Date: 2018-10-30 21:59
 * @Description:
 */
public class ConfigureWindow extends JFrame {
    
    JTextField txfIP;
    JTextField txfPort;
    JTextField txfUsername;
    JTextField txfPassword;
    //JPasswordField txfPassword;
    JTextField txfDBName;
    JTextField txfTableNames;
    
    private Set<String> tableNames;
    
    private JDBCConnector connector;
    
    public ConfigureWindow() {
        try {
            initAttributes();
            initViews();
        } catch (Exception e) {
            e.printStackTrace();
            Messages.showMessageDialog(e.getMessage(), "出错了", Messages.getErrorIcon());
        }
    }
    
    public Set<String> getTableNames() {
        if (tableNames == null) {
            tableNames = new HashSet<>();
        }
        return tableNames;
    }
    
    /**
     * 窗口属性初始化
     */
    private void initAttributes() {
        // 自身属性的设置
        this.setResizable(false);
        this.setTitle("MyBatis配置面板");
        this.setSize(500, 350);
        // 把窗口位置设置到屏幕中心
        this.setLocationRelativeTo(null);
        // 当点击窗口的关闭按钮时退出程序（没有这一句，程序不会退出）
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }
    
    /**
     * 视图初始化
     */
    private void initViews() {
        int columns = 14;
        
        // 创建中间容器（面板容器）
        // 把 面板容器 作为窗口的内容面板 设置到 窗口
        JPanel panel = new JPanel();
        this.setContentPane(panel);
        
        // 向Pne中添加组件
        // 1. 数据库IP地址
        JPanel pnlIP = new JPanel();
        JLabel lblIP = new JLabel("IP地址：");
        pnlIP.add(lblIP);
        
        txfIP = new JTextField();
        txfIP.setColumns(columns);
        txfIP.setText("127.0.0.1");
        pnlIP.add(txfIP);
        
        panel.add(pnlIP);
        
        // 2. 数据库端口，不填默认3306
        JPanel pnlPort = new JPanel();
        JLabel lblPort = new JLabel("端口号：");
        pnlPort.add(lblPort);
        
        txfPort = new JTextField();
        txfPort.setColumns(columns);
        txfPort.setText("3306");
        pnlPort.add(txfPort);
        
        panel.add(pnlPort);
        
        // 3. 数据库登录用户名
        JPanel pnlUsername = new JPanel();
        JLabel lblUsername = new JLabel("用户名：");
        pnlUsername.add(lblUsername);
        
        txfUsername = new JTextField();
        txfUsername.setColumns(columns);
        txfUsername.setText("root");
        pnlUsername.add(txfUsername);
        
        panel.add(pnlUsername);
        
        // 4. 数据库登录密码
        /*JPanel pnlPassword = new JPanel();
        JLabel lblPassword = new JLabel("密　码：");
        pnlPassword.add(lblPassword);
        
        txfPassword = new JPasswordField();
        txfPassword.setColumns(columns);
        pnlPassword.add(txfPassword);
        
        panel.add(pnlPassword);*/
        JPanel pnlPassword = new JPanel();
        JLabel lblPassword = new JLabel("密　码：");
        pnlPassword.add(lblPassword);
        
        txfPassword = new JTextField();
        txfPassword.setColumns(columns);
        txfPassword.setText("admin");
        pnlPassword.add(txfPassword);
        
        panel.add(pnlPassword);
        
        // 4. 数据库名称
        JPanel pnlDBName = new JPanel();
        JLabel lblDBName = new JLabel("数据库：");
        pnlDBName.add(lblDBName);
        
        txfDBName = new JTextField();
        txfDBName.setColumns(columns);
        txfDBName.setText("shopping");
        pnlDBName.add(txfDBName);
        
        panel.add(pnlDBName);
        
        JPanel pnlTableNames = new JPanel();
        JLabel lblTableNames = new JLabel("表　名：");
        pnlTableNames.add(lblTableNames);
        
        txfTableNames = new JTextField();
        txfTableNames.setColumns(35);
        txfTableNames.setText("把要创建的表名使用英文逗号隔开放在这里");
        pnlTableNames.add(txfTableNames);
        
        panel.add(pnlTableNames);
        
        // 创建一个基本组件（按钮），并添加到 面板容器 中
        JButton btnConfirm = new JButton("测试按钮");
        btnConfirm.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                connectInfo(event);
            }
        });
        panel.add(btnConfirm);
    }
    
    public void connectInfo(ActionEvent event) {
        
        // 获取数据库连接信息
        String ip = txfIP.getText();
        String port = txfPort.getText();
        String username = txfUsername.getText();
        //char[] password = txfPassword.getPassword();
        String password = txfPassword.getText();
        String dbName = txfDBName.getText();
        String strHandleTableNames = txfTableNames.getText();
        
        // 组织数据库连接信息
        String url = "jdbc:mysql://%s:%s/%s?useUnicode=true&amp;characterEncoding=UTF-8&amp;zeroDateTimeBehavior=convertToNull";
        url = String.format(url, ip, port, dbName);
        
        // 获取数据库现有数据库的所有表名称
        try {
            connector = new JDBCConnector("com.mysql.jdbc.Driver", url, username, password);
            DataBaseInfo dataBase = connector.getDataBaseInfo();
            
            connector.getTableInfo();
            while (resultSet.next()) {
                String tableName = resultSet.getString("TABLE_NAME");
                this.getTableNames().add(tableName);
            }
            System.out.println(tableNames);
        } catch (Exception e) {
            e.printStackTrace();
            Messages.showMessageDialog(e.getMessage(), "出错了", Messages.getErrorIcon());
        }
        
        // 校验用户输入表名
        /*String[] splits = strHandleTableNames.split(",");
        for (String split : splits) {
            boolean hasElement = false;
            for (String tableName : tableNames) {
                if (StringUtils.equals(split, tableName)) {
                    hasElement = true;
                    break;
                }
            }
            if (!hasElement) {
                Messages.showMessageDialog("输入表名异常：" + split, "数据异常", Messages.getErrorIcon());
                return;
            }
        }*/
        
        // 开始生成资源
        generateResource(connection, dbName);
        
    }
    
    private void generateResource(Connection connection, String dbName) {
        // 配置模板路径
        Configuration configure = new Configuration(Configuration.VERSION_2_3_23);
        try {
            String templates = this.getClass().getResource("/templates").getPath();
            configure.setDirectoryForTemplateLoading(new File(templates));
        } catch (IOException e) {
            Messages.showMessageDialog("模板路径异常：" + e.getMessage(), "异常提醒", Messages.getErrorIcon());
            return;
        }
        configure.setDefaultEncoding("UTF-8");
        
        // TODO 遍历table来获取表名
        String tableName = "address";
        
        // 获取表的信息封装到字典中
        LinkedHashMap<String, Object> columns = new LinkedHashMap<>();
        try {
            // 获取主键
            ResultSet primaryKeys = metaData.getPrimaryKeys(connection.getCatalog(), dbName, tableName);
            int index = 0;
            while (primaryKeys.next()) {
                String columnName = primaryKeys.getString("COLUMN_NAME");
                String key = "id" + index;
                columns.put(key, columnName);
                System.out.println(key + ":" + columnName);
            }
            
            ResultSet rsColumns = metaData.getColumns(connection.getCatalog(), dbName, tableName, "%");
            while (rsColumns.next()) {
                String columnName = rsColumns.getString("COLUMN_NAME");
                columns.put("columnName", columnName);
                Integer dataType = rsColumns.getInt("DATA_TYPE");
                columns.put("dataType", dataType);
                String typeName = rsColumns.getString("TYPE_NAME");
                columns.put("typeName", typeName);
                String remarks = rsColumns.getString("REMARKS");
                columns.put("remarks", remarks);
                int nullable = rsColumns.getInt("NULLABLE");
                columns.put("nullable", nullable);
                String columnDef = rsColumns.getString("COLUMN_DEF");
                columns.put("columnDef", columnDef);
                boolean isAutoincrement = rsColumns.getBoolean("IS_AUTOINCREMENT");
                columns.put("isAutoincrement", isAutoincrement);
                
                System.out.println("columnName:" + columnName);
                System.out.println("dataType:" + dataType);
                System.out.println("typeName:" + typeName);
                System.out.println("remarks:" + remarks);
                System.out.println("nullable:" + nullable);
                System.out.println("columnDef:" + columnDef);
                System.out.println("isAutoincrement:" + isAutoincrement);
                System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
            }
            
        } catch (SQLException e) {
            Messages.showMessageDialog(e.getMessage(), "出错了", Messages.getErrorIcon());
            return;
        }
        
        // 加载渲染模板
        Template beanMapperTemplate = null;
        try {
            beanMapperTemplate = configure.getTemplate("BeanMapper.ftl");
        } catch (IOException e) {
            Messages.showMessageDialog("加载模板异常" + e.getMessage(), "异常提醒", Messages.getErrorIcon());
            return;
        }
        
        // 开始渲染
        try (Writer out = new OutputStreamWriter(System.out)) {
            beanMapperTemplate.process(columns, out);
        } catch (TemplateException e) {
            Messages.showMessageDialog("渲染模板异常" + e.getMessage(), "异常提醒", Messages.getErrorIcon());
        } catch (IOException e) {
            Messages.showMessageDialog("处理模板异常" + e.getMessage(), "异常提醒", Messages.getErrorIcon());
        }
        
    }
    
    public void showWindow() {
        // 显示窗口，前面创建的信息都在内存中，通过 this.setVisible(true) 把内存中的窗口显示在屏幕上。
        this.setVisible(true);
    }
    
}
